<?php

namespace app\console;

use app\common\service\AccountDetail;
use app\common\service\CommissionRule;
use app\common\service\Consume;
use app\common\service\Customer;
use app\common\service\CustomerAccountLog;
use app\common\service\Goods;
use app\common\service\FootprintLog;
use app\common\service\Like;
use app\common\service\Mission;
use app\common\service\Order;
use function GuzzleHttp\default_ca_bundle;
use Predis\Client;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\Db;
use think\Exception;
use think\exception\PDOException;
use app\enumerations\MissionTypeEnum;
use app\enumerations\MissionStatusEnum;
use app\enumerations\HandleStatusEnum;
use app\enumerations\CustomerVipEnum;
use app\enumerations\AccountDetailTypeEnum;
use app\enumerations\CustomerAccountLogTypeEnum;
use app\enumerations\IsSettlementEnum;

class AsyncTask extends Command
{

    protected $server;

    protected function configure()
    {
        // setName 设置命令行名称
        // setDescription 设置命令行描述
        $this->setName('task:start')->setDescription('Start Task Server!');
    }

    protected function execute(Input $input, Output $output)
    {
        $this->server = new \swoole_server('0.0.0.0', 9501);

        // server 运行前配置
        $this->server->set([
            'worker_num' => 4,
            'daemonize' => true,
            'task_worker_num' => 4,  # task 进程数
            'log_file' => 'swoole.txt', // 日志
        ]);

        // 注册回调函数
        $this->server->on('Start', [$this, 'onStart']);
        $this->server->on('Connect', [$this, 'onConnect']);
        $this->server->on('Receive', [$this, 'onReceive']);
        $this->server->on('Task', [$this, 'onTask']);
        $this->server->on('Finish', [$this, 'onFinish']);
        $this->server->on('Close', [$this, 'onClose']);

        $this->server->start();
    }

    // 主进程启动时回调函数
    public function onStart(\swoole_server $server)
    {
        echo "Start\n";

        $missionService = new Mission();
        // 初始化未完成task任务
        $missionList = $missionService->getWaitingList(
            MissionTypeEnum::getEnumValue(MissionTypeEnum::ASYNC_CODE));

        foreach ($missionList as $mission) {
            $this->onTask($server, 0, 0, $mission["mission_code"]);
        }

    }

    // 建立连接时回调函数
    public function onConnect(\swoole_server $server, $fd, $from_id)
    {
        echo "Connect\n";
    }

    // 收到信息时回调函数
    public function onReceive(\swoole_server $server, $fd, $from_id, $data)
    {

        //投递异步任务connectSwoole
        $task_id = $server->task($data);

        $returnData = false === $task_id ? $this->swooleReturn(-2, "异步任务调用失败") : $this->swooleReturn(200);

        //将受到的客户端消息再返回给客户端
        $server->send($fd, $returnData);

    }

    // 异步任务处理函数
    public function onTask(\swoole_server $server, $task_id, $from_id, $missionCode)
    {

        $missionService = new Mission();

        $mission = $missionService
            ->findByMissionCode($missionCode);

        if (isNullOrEmpty($mission)) {
            return false;
        }

        if ($mission["status"] !=
            MissionStatusEnum::getEnumValue(MissionStatusEnum::WAITING_CODE)) {
            return false;
        }

        // 更新任务已完成
        $missionData["status"] = 1;
        $missionData["end_time"] = getCurrentTime();

        $missionService->updateByIdAndData($mission["id"], $missionData);

        $taskData = json_decode($mission["param"], true);
        $taskType = $taskData["task_type"];

        Db::startTrans();

        try {

            switch ($taskType) {

                //初始化未完成任务
                case "initMissionListKey":

                    // 获取未完成任务列表
                    $missionList = $missionService->getWaitingList();

                    foreach ($missionList as $mission) {

                        if ($mission["mission_type"] ==
                           MissionTypeEnum::getEnumValue(MissionTypeEnum::SETTIMEOUT_CODE)) {
                            setTimeoutTask($mission["execute_time"],
                                $mission["mission_code"]);
                        } else {
                            asyncTask($mission["mission_code"]);
                        }

                    }

                    break;

                default:
                    break;
            }


            Db::commit();

        } catch (PDOException $exception) {

            var_dump($exception);

            Db::rollback();

        }

        $server->finish(json_encode($taskData));

    }

    // 异步任务完成通知 Worker 进程函数
    public function onFinish(\swoole_server $server, $task_id, $result)
    {
        echo "onFinish\n";
    }

    // 关闭连时回调函数
    public function onClose(\swoole_server $server, $fd, $from_id)
    {
        echo "Close\n";
    }

    //调用返回
    protected function swooleReturn($code, $msg = "", $data = "")
    {
        $returnData["code"] = $code;
        $returnData["msg"] = $msg;
        $returnData["data"] = $data;

        return json_encode($returnData);
    }

}